package top.hekun.study.core;

import org.objectweb.asm.ClassWriter;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
 * 〈通过代码生成一个类的字节码〉
 *
 * @author: Sakura
 * @date: 2023/4/23
 */
public class HelloWordDumo {


    /**
     * 生成一个类文件 top.hekun.study.core.model.HelloWord
     * 并重写toString 输入 "这是一个demo"
     *
     * @return
     */
    public static byte[] dump() {
        // 一个字节码 写对象 设置从头开始计算帧
        ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        /**
         * 设置类信息
         * 版本为 java8
         *  access  访问标识, 公有  私有 抽象类 接口等
         * 生成一个包名是 top.hekun.study.core.model
         * 类名是HelloWord
         * 继承父类为 java/lang/Object
         * signature 签名为null
         * interfaces 继承接口为null
         */
        classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, "top/hekun/study/model/HelloWord", null, "java/lang/Object", null);

        {
            /**
             * 添加构造方法
             *  access  访问标识, 公有  私有 抽象类 接口等
             * 方法名称 <init>
             * 方好类型 ()V 无参数 无返回
             *  signature 签名为null
             *  exceptions 例外 我理解为异常情况
             */
            MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
            methodVisitor.visitCode();
            // 调用父类的构造方法
            methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
            methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            methodVisitor.visitInsn(Opcodes.RETURN);

            methodVisitor.visitMaxs(1, 1);
            methodVisitor.visitEnd();
        }
        {
            /**
             * 添加toString 方法
             */
            MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
            methodVisitor.visitCode();
            // 对应的返回的字符串
            methodVisitor.visitLdcInsn("这是一个demo");
            methodVisitor.visitInsn(Opcodes.ARETURN);
            methodVisitor.visitMaxs(1, 1);
            methodVisitor.visitEnd();
        }

        classWriter.visitEnd();
        return classWriter.toByteArray();
    }
}
